package com.hmdp.service.impl;

import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.Blog;
import com.hmdp.entity.User;
import com.hmdp.mapper.BlogMapper;
import com.hmdp.service.IBlogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IUserService;
import com.hmdp.utils.SystemConstants;
import com.hmdp.utils.UserHolder;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 */
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
    @Resource
    private IUserService userService;
    @Resource
    private BlogMapper blogMapper;
    @Resource
    private ThreadPoolTaskExecutor taskExecutor; // 线程池异步处理
    // 注入 Redis 模板
    private final StringRedisTemplate stringRedisTemplate;
    public BlogServiceImpl(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    // 点赞状态常量
    private static final int LIKE_ACTION = 1;
    private static final int UNLIKE_ACTION = -1;

    @Override
    public Result queryBlogid(Long id) {
      Blog blog =blogMapper.getById(id);
//        Blog blog =getById(id);
        extracted(blog);
        isBlogLied(blog);
        return  Result.ok(blog);
    }

    private void isBlogLied(Blog blog) {
        Long userId = null;
        try {
            //1.获取登录用户
            userId = UserHolder.getUser().getId();
        } catch (Exception e) {
            log.debug("用户未登录！");
            return;
        }
        //2.判断当前用户是否已经点赞过
        String key = "blog:liked:" +blog.getId();
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        try {
            blog.setIsLike(BooleanUtil.isTrue(isMember));
        } catch (Exception e) {
            log.debug("点赞信息为空！");
        }


    }

    private void extracted(Blog blog) {
        Long userId = blog.getUserId();
        User user = userService.getById(userId);
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
    }

    @Override
    public Result queryBloghot(Integer current) {
        // 根据用户查询
        Page<Blog> page = query()
                .orderByDesc("liked")
                .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 获取当前页数据
        List<Blog> records = page.getRecords();
        // 查询用户
        records.forEach(blog->{this.extracted(blog);
        this.isBlogLied(blog);});



        return Result.ok(records);

    }


    @Override
    public Result likeBlog(Long blogId) {
        Long userId = UserHolder.getUser().getId();
        String likeKey = "blog:liked:" + blogId;
        String changeKey = "blog:like:change";

        // 1. 判断当前用户点赞状态
        Boolean isLiked = stringRedisTemplate.opsForSet().isMember(likeKey, userId.toString());

        // 2. 计算操作类型 (1点赞/-1取消)
        int action = Boolean.TRUE.equals(isLiked) ? UNLIKE_ACTION : LIKE_ACTION;

        // 3. 原子操作更新Redis状态
        stringRedisTemplate.execute(new SessionCallback<Object>() {
            @Override
            public Object execute(RedisOperations operations) {
                operations.multi(); // 开启事务
                if (action == LIKE_ACTION) {
                    operations.opsForSet().add(likeKey, userId.toString());
                } else {
                    operations.opsForSet().remove(likeKey, userId.toString());
                }
                // 记录点赞变化量 (Hash结构: key=blogId, value=增量)
                operations.opsForHash().increment(changeKey, blogId.toString(), action);
                return operations.exec(); // 提交事务
            }
        });

        // 4. 异步处理数据库更新
        taskExecutor.execute(() -> processLikeChange(blogId));
        return Result.ok();
    }

    // 异步批量处理点赞变化
    private void processLikeChange(Long blogId) {
        String changeKey = "blog:like:change";

        // 5. 获取并清零该博客的变化量
        Long delta = stringRedisTemplate.opsForHash().increment(changeKey, blogId.toString(), 0);
        if (delta == 0) return; // 无变化直接返回

        stringRedisTemplate.opsForHash().put(changeKey, blogId.toString(), "0");

        // 6. 批量更新数据库 (MyBatis-Plus实现)
        updateBatchLikeCount(blogId, delta);
    }

private void updateBatchLikeCount(Long blogId, Long delta) {
    update()
        .setSql("liked = liked + " + delta.intValue()) // 安全拼接数值
        .eq("id", blogId)
        .update();



    }
}

